home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
ddj0492.zip
/
STRUCPRG.ASC
< prev
next >
Wrap
Text File
|
1992-03-10
|
8KB
|
248 lines
_STRUCTURED PROGRAMMING COLUMN_
by Jeff Duntemann
[LISTING ONE]
UNIT DirList; { By Jeff Duntemann; for DDJ 4/92 }
INTERFACE
USES Crt,DOS,Objects, { Standard Borland units }
When2; { From DDJ 1/91 }
TYPE
String40 = STRING[40];
PDirEntry = ^TDirEntry;
TDirEntry =
OBJECT(TObject)
Path : PathStr; { Predefined in Dos unit as STRING[79] }
Entry : SearchRec; { Also predefined in the Dos unit }
DirLine : String40; { Preformatted directory info string }
CONSTRUCTOR Init(APath : PathStr; ASearchRec : SearchRec);
PROCEDURE FormatDirLine;
END;
PDirEntryCollection = ^TDirEntryCollection;
TDirEntryCollection =
OBJECT(TSortedCollection)
CONSTRUCTOR InitDir(ALimit,ADelta : Integer;
Path, Mask : STRING;
Attr : Word);
CONSTRUCTOR InitCommandLine(ALimit,ADelta : Integer; StartParam : Integer);
CONSTRUCTOR InitTree(Alimit,ADelta : Integer;
Path,Mask : STRING;
Attr : Word);
FUNCTION Compare(Key1,Key2 : Pointer) : Integer; VIRTUAL;
PROCEDURE AddDir(Path,Mask : STRING;
Attr : Word);
PROCEDURE TreeScan(Path,Mask : STRING; Attr : Word);
END;
IMPLEMENTATION
VAR
Stamp : When; { Global When stamp for time/date string processing }
{----------------------------------------}
{ Methods: TDirEntry }
{----------------------------------------}
CONSTRUCTOR TDirEntry.Init(APath : PathStr; ASearchRec : SearchRec);
BEGIN
TObject.Init;
Path := APath;
Entry := ASearchRec;
FormatDirLine;
END;
PROCEDURE TDirEntry.FormatDirLine;
VAR
DotPos : Integer;
WorkString,Blanker : String40;
BEGIN
Stamp.PutWhenStamp(Entry.Time);
DirLine := ' ';
Blanker := DirLine;
{If the entry has the directory attribute, format differently: }
IF (Entry.Attr AND $10) <> 0 THEN { Bit 4 is the directory attribute }
BEGIN
Insert(Entry.Name,DirLine,1); { No extensions on subdirectory names }
Insert('<DIR>',DirLine,14) { Tell the world it's a subdirectory }
END
ELSE
{This compound statement separates the file from its extension }
{ and converts the file size to a string. Note that we did not }
{ insert a file size figure into DirLine for subdirectory entries. }
BEGIN
DotPos := Pos('.',Entry.Name);
IF DotPos > 0 THEN { File name has an extension }
WorkString := Copy(Entry.Name,1,DotPos-1) +
Copy(Blanker,1,9-DotPos) + '.' +
Copy(Entry.Name,DotPos+1,Length(Entry.Name)-DotPos)
ELSE { File name has no extension }
WorkString := Entry.Name +
Copy(Blanker,1,8-Length(Entry.Name)) + '.';
Insert(WorkString,DirLine,1);
Str(Entry.Size:7,WorkString);
Insert(WorkString,DirLine,15);
END;
Insert(Stamp.GetDateString,DirLine,24);
Insert(Stamp.GetTimeString,DirLine,34); { Finally, insert the time }
Delete(DirLine,42,Length(DirLine)-42);
END;
{----------------------------------------}
{ Methods: TDirEntryCollection }
{----------------------------------------}
CONSTRUCTOR TDirEntryCollection.InitDir(ALimit,ADelta : Integer;
Path,Mask : STRING;
Attr : Word);
BEGIN
TSortedCollection.Init(Alimit,ADelta);
AddDir(Path,Mask,Attr);
END;
CONSTRUCTOR TDirEntryCollection.InitCommandLine(ALimit,ADelta : Integer;
StartParam : Integer);
VAR
I : Integer;
SR : SearchRec; { Defined in the Dos unit }
DEP : PDirEntry;
Path : PathStr; { Defined in the Dos unit as STRING[79]; }
Dir : DirStr; { Defined in the Dos unit as STRING[67]; }
Name : NameStr; { Defined in the Dos unit as STRING[8]; }
Ext : ExtStr; { Defined in the Dos unit as STRING[4]; }
BEGIN
TSortedCollection.Init(ALimit,ADelta);
FOR I := StartParam TO ParamCount DO
BEGIN
FSplit(ParamStr(I),Dir,Name,Ext);
AddDir(Dir,Name+Ext,AnyFile);
END;
END;
CONSTRUCTOR TDirEntryCollection.InitTree(Alimit,ADelta : Integer;
Path,Mask : STRING;
Attr : Word);
BEGIN
TSortedCollection.Init(Alimit,ADelta);
TreeScan(Path,Mask,Attr);
END;
FUNCTION TDirEntryCollection.Compare(Key1,Key2 : Pointer) : Integer;
BEGIN
IF (PDirEntry(Key1)^.Path + PDirEntry(Key1)^.Entry.Name) =
(PDirEntry(Key2)^.Path + PDirEntry(Key2)^.Entry.Name) THEN
Compare := 0
ELSE
IF (PDirEntry(Key1)^.Path + PDirEntry(Key1)^.Entry.Name) <
(PDirEntry(Key2)^.Path + PDirEntry(Key2)^.Entry.Name) THEN
Compare := -1
ELSE Compare := 1;
END;
PROCEDURE TDirEntryCollection.AddDir(Path,Mask : STRING;
Attr : Word);
VAR
I : Integer;
SR : SearchRec;
DEP : PDirEntry;
BEGIN
FindFirst(Path+Mask,Attr,SR);
IF DosError = 0 THEN
BEGIN
DEP := New(PDirEntry,Init(Path,SR));
Insert(DEP);
REPEAT
FindNext(SR);
IF DosError = 0 THEN
BEGIN
DEP := New(PDirEntry,Init(Path,SR));
Insert(DEP);
END;
UNTIL DosError <> 0;
END;
END;
PROCEDURE TDirEntryCollection.TreeScan(Path,Mask : STRING;
Attr : Word);
VAR
I : Integer;
SR : SearchRec;
DEP : PDirEntry;
NextDirectory : STRING;
BEGIN
fillchar(SR,sizeof(SR),0);
{ We look for and search any subdirectories first: }
IF Path <> '\' THEN Path := Path + '\';
FindFirst(Path+'*.*',Directory,SR);
WHILE (DOSError <> 2) AND (DOSError <> 18) DO
BEGIN
IF ((SR.Attr AND Directory) = Directory )
AND (SR.Name[1] <> '.') THEN { We have a subdirectory }
BEGIN
NextDirectory := Path + SR.Name;
TreeScan(NextDirectory,Mask,Attr);
END;
FindNext(SR);
END;
{ At this point, we're in a directory that has no unsearched }
{ subdirectories, so we can search for files matching Mask: }
AddDir(Path,Mask,Attr);
END;
{ No initialization section }
END.
[LISTING TWO]
PROGRAM JFind; { By Jeff Duntemann; from DDJ 4/92 }
USES DOS,CRT,Printer, { Standard Borland units }
DirList; { From DDJ for 4/92 }
VAR
Console : TEXT;
FileSpecs : STRING;
I : Integer;
FilesFound : PDirEntryCollection;
PROCEDURE DisplayFoundFiles(FilesFound : PDirEntryCollection);
{ This is the FAR local routine passed to the iterator method. }
{ It's called once for each item in the collection: }
PROCEDURE DisplayOneFile(Target : PDirEntry); FAR;
BEGIN
Write(Console,Copy(Target^.DirLine,13,Length(Target^.DirLine)),' ');
Writeln(Console,Target^.Path,Target^.Entry.Name);
END;
BEGIN
{ This is how you iterate a procedure over a collection: }
FilesFound^.ForEach(@DisplayOneFile);
END;
BEGIN { JFIND Main }
Assign(Console,''); { This allows us to use Standard Output }
Rewrite(Console); { for Write/Writeln statements }
IF ParamCount = 0 THEN
BEGIN
Writeln(Console,'>>>JFIND<<< by Jeff Duntemann');
Writeln(Console);
Writeln(Console,'Invocation syntax:');
Writeln(Console);
Writeln(Console,' JFIND <filespec>,[<filespec>..] CR');
Writeln(Console);
END
ELSE
BEGIN
FilesFound := New(PDirEntryCollection,Init(256,16));
FOR I := 1 TO ParamCount DO
FilesFound^.TreeScan('\',ParamStr(I),AnyFile);
IF FilesFound^.Count > 0 THEN
BEGIN
DisplayFoundFiles(FilesFound);
Writeln(Console);
END
ELSE
Writeln(Console,'No files match that file spec.');
END;
END.